package pwd.allen.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.ibatis.session.Configuration;
import pwd.allen.enums.StatusEnum;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Map;

/**
 * mybatis-plus初始化时会解析注解并生成TableInfo，逻辑见：{@link TableInfoHelper#initTableInfo(Configuration, String, Class)}
 * @author 门那粒沙
 * @create 2020-06-16 23:27
 **/
@TableName(
        value = "db_user"
        , autoResultMap = true
//        , excludeProperty = {"deleted"}
)
@Data
@ApiModel(value = "用户实体",description = "用户实体")
public class User extends Model<User> {

    /**
     * 标注主键，如果不标注，如果存在id属性，则默认用id作为主键 {@link TableInfoHelper#initTableIdWithoutAnnotation(GlobalConfig.DbConfig, TableInfo, Field)}
     * 如果没有主键，则无法使用plus提供的xxxById的方法，逻辑见：{@link DefaultSqlInjector#getMethodList(Class, TableInfo)}
     *
     *  id:字段名
     *  type:主键类型
     *      ASSIGN_ID：分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId
     *      ASSIGN_UUID：分配UUID(主键类型为String)，使用接口IdentifierGenerator的方法nextUUID
     *      AUTO：数据库ID自增，好像即使手动设置id也不会传
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Integer id;
    @TableField("user_name")
    @ApiModelProperty(value = "用户名")
    private String name;
    @TableField(updateStrategy = FieldStrategy.IGNORED) //为空时也更新到数据库
    private Integer age;
    private StatusEnum status;
    private Integer deptId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createAt;

    /**
     * 字段注解(非主键)
     *  value：数据库字段名
     *  exist：false时不做映射
     */
    @TableField(exist = false)
    private Department dept;
    @TableField(fill = FieldFill.INSERT_UPDATE) //插入或者更新都进行填充处理，需借助MetaObjectHandler，判断优先级比 {@link FieldStrategy} 高
    private byte[] msg;

    /**
     * 逻辑删除字段，null未删除 1已删除
     */
    @TableLogic(value = "null", delval = "1")
    private Integer deleted;

    /**
     * 会将值转成json字符串存储，如果想从json转成java对象，需要借助resultMap（设置tableName.autoResultMap=true或者自定义resultMap时设置typeHandler）
     * 如果自定义的方法resultType指定实体类，details会是null，需要指定resultMap并配置typeHandler才行
     * resultMap配置typeHandler的方式：直接指定typeHandler；或者设置autoResultMap=true，并在实体类的对应字段上的注解指定typeHandler
     * 类型好像不能是String，否则会报错，可以是自定义实体类或者Map，会自动识别
     * 如果自定义了resultMap，则相应的属性要配置typeHandler，否则可能报错找不到typeHandler
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Map<String, Object> details;
}
